# -*- coding: utf8 -*-

from sintatico import *
from lexico import token
from semantico import semantico
from constantes import *

class Sintatico:
    #estado corrente
    estado = 1
    estadoAnterior = 1
    # pilha de máquina
    pilha = []
    # maquina corrente
    maquina_txt = 'programa'
    
    #
    tipo = ''
    identificador = ''
    
    # analisador semantico
    semantico = None
    
    def IniciarAnalisadorSemantico(self, tabelaDeSimbolos):
        print 'semantico inicio'
        self.semantico = semantico.Semantico(tabelaDeSimbolos)
    
    def Maquina(self, token):
        if token.definicao == "Pontuacao":
            parte = token.token
        elif token.definicao == 'Inteiro':
            parte = 'Inteiro'
        elif token.definicao == "Reservada":
            parte = token.token
        else:
            parte = 'identificador'
            self.identificador = token.token
        
        if maquina.has_key((self.maquina_txt, self.estado, parte)):
            # transicao de estado
            self.estadoAnterior = self.estado
            self.estado = maquina[(self.maquina_txt, self.estado, parte)]
            print 'SINTATICO - maquina: ' + self.maquina_txt + ' , estado:' + str(self.estado) + ', parte:' + parte
            
            # acoes semanticas
            if self.maquina_txt == 'programa':
                if self.estado == 2:
                    self.semantico.IniciarCodigoObjeto()
                elif self.estadoAnterior == 33:
                    self.semantico.TerminarCodigoObjeto()
                    self.semantico.GravaNoArquivo()
                # guarda o tipo
                elif self.estado == 6 or self.estado == 10:
                    self.tipo = parte
                # guarda o tipo na tabela de simbolos e gera codigo
                elif self.estado == 7 or self.estado == 11:
                    print 'SEMANTICO Declara: ' + token.token
                    self.semantico.DeclaraVariavel(token.token, self.tipo)
            # tratamento semantico das maquinas de comando
            elif self.maquina_txt == 'comando':
                #atribuicao , transicao 5->2
                if self.estado == 3 and self.estadoAnterior == 2:
                    print 'SEMANTICO 2->5: ' + token.token
                    if parte == 'identificador':
                        self.semantico.ArmazenarIdentificador(token.token)
                
                
            # aplica as ações semânticas na maquina expressao
            elif self.maquina_txt == 'expressao':
                if (self.estado == 2 or self.estado == 15) and (parte == 'Inteiro' or parte == 'identificador' or parte == 'Identificador'):
                    self.semantico.EmpilhaOperando(token.token, token.definicao)
                # trata o ')'
                elif (self.estado == 4 or self.estado == 9 or self.estado == 14 or self.estado == 19 or self.estado == 20) and token.token == ')': 
                    self.semantico.FecharParenteses()
                # trata +,-,*,/
                elif (self.estado == 11 or self.estado == 15):
                    self.semantico.TratarOperador(token.token)
                # trata '('
                elif (self.estado == 11 or self.estado == 6 or self.estado == 16) and token.token == '(':
                    self.semantico.EmpilhaOperador(token.token)
                      
        elif maquina.has_key((self.maquina_txt, self.estado,'expressao')):
            print 'SINTATICO - maquina: ' + self.maquina_txt + ' , estado:' + str(self.estado) + ', parte:' + parte
            print 'SINTATICO - empilhar ' + self.maquina_txt + ' , estado: ' + str(maquina[(self.maquina_txt, self.estado,'expressao')]) + ', parte:' + parte
            print 'SINTATICO - foi para a máquina expressao'
            self.pilha.append((self.maquina_txt, maquina[(self.maquina_txt,self.estado,'expressao')], self.estado))
            self.estado = 1
            self.maquina_txt = 'expressao'
            if maquina.has_key((self.maquina_txt, self.estado, parte)):
                self.estado = maquina[(self.maquina_txt, self.estado, parte)]
                print 'SINTATICO - maquina: ' + self.maquina_txt + ' , estado:' + str(self.estado)
                
                if parte == 'identificador':
                    self.semantico.EmpilhaOperando(token.token, parte)
                    print 'SEMANTICO - Empilhou operando ' + token.token
                elif parte == 'Inteiro':
                    self.semantico.EmpilhaOperando(token.token, parte)
                    print 'SEMANTICO - Empilhou operando ' + token.token
            else:
                print 'SINTATICO - falhou - expressao'
        elif maquina.has_key((self.maquina_txt, self.estado,'sequencia-comandos')):
            print 'SINTATICO - maquina: ' + self.maquina_txt + ' , estado:' + str(self.estado) + ', parte:' + parte
            print 'SINTATICO - empilhar ' + self.maquina_txt + ' , estado: ' + str(maquina[(self.maquina_txt, self.estado,'sequencia-comandos')]) + ', parte:' + parte
            print 'SINTATICO - foi para a máquina comandos'
            self.pilha.append((self.maquina_txt, maquina[(self.maquina_txt,self.estado,'sequencia-comandos')], self.estado ))
            self.estado = 2
            self.maquina_txt = 'comando'
            if maquina.has_key((self.maquina_txt, self.estado, parte)):
                self.estado = maquina[(self.maquina_txt, self.estado, parte)]
                print 'SINTATICO - maquina: ' + self.maquina_txt + ' , estado:' + str(self.estado)
                
                if parte == 'identificador':
                    self.semantico.ArmazenarIdentificador(token.token)
                
            else:
                print 'falhou - comando'
        elif self.maquina_txt == 'programa' and self.estado == 33:
            print 'SINTATICO - aceitou'
        else:
            if self.maquina_txt == 'expressao' and (self.estado == 2 or self.estado == 15):
                print 'SINTATICO - aceitou máquina de expressao'
                        
            print 'Pilha:' + str(len(self.pilha))
            if len(self.pilha) > 0 :
                pops = self.pilha.pop()
                print pops
                
                if self.maquina_txt == 'expressao':
                    while len(self.semantico.pilha_operadores) > 0:
                        self.semantico.GeraCodigoExpressao()
                        self.semantico.CopiaExpressaoParaObjeto()
                
                self.maquina_txt, self.estado, self.estadoAnterior = pops[0], pops[1], pops[2]
                print 'desempilha maquina:' + self.maquina_txt + ' , estado: ' + str(self.estado)
                
                # acoes semanticas
                if self.maquina_txt == 'comando':
                    # atribuicao, transicao 4->5->2 da maquina comando
                    if self.estado == 5 and self.estadoAnterior == 4:
                        print 'SEMANTICO 4->5: ' + token.token  
                        self.semantico.AtribuirValor(self.semantico.identificador)
                # fim das ações semânticas
                
                if maquina.has_key((self.maquina_txt, self.estado, parte)):
                    self.estado = maquina[(self.maquina_txt, self.estado, parte)]
                    print 'maquina: ' + self.maquina_txt + ' , estado:' + str(self.estado)
                
                if self.maquina_txt == 'programa' and self.estado == 33:
                    print "aceitou"
                    self.semantico.TerminarCodigoObjeto()
                    self.semantico.GravaNoArquivo()

            else:
                print "falhou 2"
    
        # aplica as ações semânticas na maquina expressao
        '''
        if self.maquina_txt == 'expressao':
            if (self.estado == 2 or self.estado == 15) and (parte == 'Inteiro' or parte == 'identificador'):
                self.semantico.EmpilhaOperando(token.token, token.definicao)
            # trata o ')'
            elif (self.estado == 4 or self.estado == 9 or self.estado == 14 or self.estado == 19 or self.estado == 20) and token.token == ')': 
                self.semantico.FecharParenteses()
            # trata +,-,*,/
            elif (self.estado == 4 or self.estado == 15):
                self.semantico.TratarOperador(token.token)
            # trata '('
            elif (self.estado == 11 or self.estado == 6 or self.estado == 16) and token.token == '(':
                self.semantico.EmpilhaOperador(token.token)
                '''
    

    def __init__(self, entrada):
        self.texto = entrada
        
    def Executar(self, token):
        print 'teste'

    def pegarEstado(self):
        return self.estado
    
    def AceitaExpressao(self):
        if self.maquina_txt == 'expressao' and (self.estado == 2 or self.estado == 15):
            return True
        elif self.maquina_txt == 'comando' and self.estado == 2:
            return True
        elif self.maquina_txt == 'programa' and self.estado == 33:
            return True
        return False
    
    def Log(self, log):
        print 'a'
        